/*
** Haaf's Game Engine 1.7
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** Vector2 helper class
*/


#ifndef HGEVECTOR_H
#define HGEVECTOR_H


#include "hge.h"
#include <math.h>


/*
** Fast 1.0/sqrtf(float) routine
*/
float InvSqrt(float x);

class Vector2
{
public:
	Vector2(void) {}
	Vector2(float x, float y) : d_x(x), d_y(y) {}

	Vector2& operator*=(const Vector2& vec)
	{
		d_x *= vec.d_x;
		d_y *= vec.d_y;

		return *this;
	}

	Vector2& operator/=(const Vector2& vec)
	{
		d_x /= vec.d_x;
		d_y /= vec.d_y;

		return *this;
	}

	Vector2& operator+=(const Vector2& vec)
	{
		d_x += vec.d_x;
		d_y += vec.d_y;

		return *this;
	}

	Vector2& operator-=(const Vector2& vec)
	{
		d_x -= vec.d_x;
		d_y -= vec.d_y;

		return *this;
	}

	Vector2 operator+(const Vector2& vec) const
	{
		return Vector2(d_x + vec.d_x, d_y + vec.d_y);
	}

	Vector2 operator-(const Vector2& vec) const
	{
		return Vector2(d_x - vec.d_x, d_y - vec.d_y);
	}

	Vector2 operator*(const Vector2& vec) const
	{
		return Vector2(d_x * vec.d_x, d_y * vec.d_y);
	}

	bool operator==(const Vector2& vec) const
	{
		return ((d_x == vec.d_x) && (d_y == vec.d_y));
	}

	bool operator!=(const Vector2& vec) const
	{
		return !(operator==(vec));
	}

	Vector2& operator+=(float scale)
	{
		d_x += scale;
		d_y += scale;
		return *this;
	}

	Vector2	operator/  (const float scalar)	const { return Vector2(d_x/scalar, d_y/scalar); }
	Vector2	operator*  (const float scalar) const { return Vector2(d_x*scalar, d_y*scalar); }
	Vector2&	operator*= (const float scalar)		  { d_x*=scalar; d_y*=scalar; return *this;   }
	
	float		Dot(const Vector2 *v) const { return d_x*v->d_x + d_y*v->d_y; }
	float		Length() const { return sqrtf(Dot(this)); }
	float		Angle(const Vector2 *v = 0) const;
	
	void Clamp(const float max)
	{
		if(Length() > max)
		{
			Normalize();
			d_x *= max; d_y *= max;
		}
	}

	Vector2* Normalize()
	{
		float rc = InvSqrt( Dot(this) );
		d_x *= rc;
		d_y*=rc;
		return this;
	}

	Vector2* Rotate(float a);

	float d_x, d_y;
};

inline Vector2	 operator* (const float s, const Vector2 &v)		{ return v*s; }
inline float	 operator^ (const Vector2 &v, const Vector2 &u) { return v.Angle(&u); }
inline float	 operator% (const Vector2 &v, const Vector2 &u) { return v.Dot(&u); }

class Vector3
{
public:
	Vector3(void) {}
	Vector3(float x, float y, float z) : d_x(x), d_y(y), d_z(z) {}

	bool operator==(const Vector3& vec) const
	{
		return ((d_x == vec.d_x) && (d_y == vec.d_y) && (d_z == vec.d_z));
	}

	bool operator!=(const Vector3& vec) const
	{
		return !(operator==(vec));
	}

	float d_x, d_y, d_z;
};


#endif
